package test.aspect;

import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import test.annotation.ServiceConfig;
import test.annotation.ServiceMapping;
import test.context.JsonContext;
import test.in.EsbIn;
import test.utils.SpringUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Created with IntelliJ IDEA.
 *
 * @ project name : example
 * @ Author: XuLeHuang
 * @ Date: 2022/11/16 22:32
 * @ Description:
 */
@Component
@Aspect
public class ServiceCallAspect {

    @Autowired
    private EsbIn esbIn;

    @Pointcut("@annotation(test.annotation.ServiceConfig)")
    public void serviceConfigPointCut() {

    }

    @Before(value = "serviceConfigPointCut() && @annotation(serviceConfig)")
    public void ServiceCall(JoinPoint joinPoint, ServiceConfig serviceConfig) throws InstantiationException {
        //@ServiceConfig标注的方法
        /*MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();*/

        String originalPath = serviceConfig.originalPath().replace("/", "");

        Class<?> value = serviceConfig.value();
        Method[] declaredMethods = value.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            ServiceMapping serviceMapping = declaredMethod.getAnnotation(ServiceMapping.class);
            String path = serviceMapping.path();
            if (originalPath.equals(path)) {
                try {
                    //EsbIn esbIn = (EsbIn) value.newInstance();
                    //EsbIn esbIn = (EsbIn)SpringUtil.getBean(value);

                    /**
                     * 参数值拿到了，考虑类型动态转换的问题，已解决
                     *多参数：已解决
                     * 如何将in里面的值跟后置通知连起来
                     * */
                    Object[] args = joinPoint.getArgs();
                    int length = args.length;
                    for (int i = 0; i < length; i++) {
                        System.out.println(args[i]);
                    }
                    Object reqJsonObject =  args[0];
                    JSONObject rspJsonObject = new JSONObject();
                    JsonContext jsonContext = (JsonContext)args[1];
                    jsonContext.setReqJsonObject(reqJsonObject);
                    jsonContext.setRspJsonObject(rspJsonObject);
                    declaredMethod.invoke(esbIn, jsonContext);
                    /*HttpServletResponse response = (HttpServletResponse) args[1];
                    try {
                        response.getWriter().write(jsonContext.getResponseBean().toString());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }*/
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /*@After(value = "serviceConfigPointCut() && @annotation(serviceConfig)")
    public Object ServiceCallAfter(JoinPoint joinPoint, ServiceConfig serviceConfig) throws InstantiationException {
        String originalPath = serviceConfig.originalPath().replace("/", "");

        Class<?> value = serviceConfig.value();
        Method[] declaredMethods = value.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            ServiceMapping serviceMapping = declaredMethod.getAnnotation(ServiceMapping.class);
            String path = serviceMapping.path();
            if (originalPath.equals(path)) {
                Parameter[] parameters = declaredMethod.getParameters();
                for (Parameter parameter : parameters) {
                    System.out.println(parameter);
                }
                *//*AbstractContext abstractContext = (AbstractContext) args[0];
                Object responseBean = abstractContext.getResponseBean();*//*
                return null;
            }
        }
        return null;
    }*/
}
